#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "gps.h"
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>

typedef struct gps_data_t *GPSDATA;
GPSDATA gpsdata0, gpsdata1;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int validdata = 0;

void gpsd_Callback(GPSDATA gpsdata0,
		char *buf, 
		size_t len)
{
	fprintf(stderr, "in callback\n");
	pthread_mutex_lock( &mutex );
	gpsdata1 = gpsdata0;
	pthread_mutex_unlock( &mutex );	

	fprintf(stderr, "leaving callback\n");
	validdata = 1;
}

int gps_connect()
{
	fprintf(stderr, "Initializing GPS connection\n");
	
	fprintf(stderr, "GPSD_API_MAJOR_VERSION %d, 4 needed\n", GPSD_API_MAJOR_VERSION);
	fprintf(stderr, "GPSD_API_MINOR_VERSION %d, 1 needed\n", GPSD_API_MINOR_VERSION);
	//char host[] = "127.0.0.1";
	//char port[] = "2947";
	gpsdata0 = NULL;
	gpsdata0 = gps_open("localhost", "2947"); //, gpsdata0);
	//fprintf(stderr, "%d returned\n", ret);

	//char *err_str = gps_errstr(ret);
	//fprintf(stderr, "%s\n", err_str);
	int ret = 0;
	if (gpsdata0==NULL)
	{	
		fprintf(stderr, "%d errno\n", errno);
		ret = -1;
	}
	if (ret<=-1) {
		//char *err_str = gps_errstr(ret);
/*
		char err_str[50];
		switch (errno) {
		case NL_NOSERVICE:
			sprintf(err_str, "can't get service entry");
			break;
		case NL_NOHOST:
			sprintf(err_str, "can't get host entry");
			break;
		case NL_NOPROTO:
			sprintf(err_str, "can't get protocol entry");
			break;
		case NL_NOSOCK:
			sprintf(err_str, "can't create socket");
			break;
		case NL_NOSOCKOPT:
			sprintf(err_str, "error SETSOCKOPT SO_REUSEADDR");
			break;
		case NL_NOCONNECT:
			sprintf(err_str, "can't connect to host");
			break;
		default:
			sprintf(err_str, "Unknown\n");
			break;
		}
		fprintf(stderr,
		    "No gpsd running or network error: %d, %d, %s\n",
		    errno, ret, err_str);
*/
		fprintf(stderr, "GPS connection error!!\n");
		exit(1);
	}
	fprintf(stderr, "GPS connected\n");
//	static pthread_t handler;
//	gps_set_callback(gpsdata0, gpsd_Callback, &handler);

	gps_set_raw_hook(gpsdata0, gpsd_Callback);
   (void)gps_stream(gpsdata0, WATCH_ENABLE, NULL);

	validdata = 0;
	return 0;
}

int gps_disconnect()
{
	gps_close(gpsdata0);
	return 0;
}

int gps_fetch(gps_data_t* newData)
{
	if(gps_poll(gpsdata0) != 0)
	{
		printf("ack1!\n");
		exit(-2);
	}
	int toReturn = 0;
	pthread_mutex_lock( &mutex );
//	fprintf(stderr, "In fetch\n");
	if(validdata == 1)
	{
//		fprintf(stderr, "valid data\n");
//		if (gpsdata1->status > 0)
//		{
			toReturn = 1;
			*newData = *gpsdata1;
//		}
	}
	pthread_mutex_unlock( &mutex );
	return toReturn;
}
